/*
    能将*.js 文件编译为*.class文件,
    能将*.class 文件压缩为*.jar文件,
    能将*.jar 文件转换为*.dex文件,
    能将*.jar 文件转换为含dex的jar文件,
    能非全局加载 dex文件, 且不容易卡死
    如遇到问题请重启解决
*/
runtime.loadDex("./jarDex.dex");
importClass("com.android.dx.command.dexer.Main");
var js2dexTool = new function() {
    /*
        优化jar包,使其 runtime.loadJar 加载更快
        通过复制加载过的缓存实现
        jarFile 要转换的绝对路径
        dexFile 要输出的绝对路径
    */
    this.jarFileToClassesJarFile = function jarFileToClassesJarFile(jarFile, dexFile) {
        jarFile = new java.io.File(jarFile)
        var dexFilename = com.stardust.util.MD5.md5(jarFile + "_" + jarFile.lastModified())
        var mdexFile = new java.io.File(context.getCacheDir(), "classes/" + dexFilename)
        if (mdexFile.exists()) {
            files.copy(mdexFile, dexFile)
        } else {
            runtime.loadJar(jarFile)
            files.copy(mdexFile, dexFile)
        }
    }

    /*
        将多个含*.class文件的jar包,合成一个dex文件
        通过自带第三方类实现
        jarFiles 要转换的绝对路径数组
        dexFile 要输出的绝对路径
    */
    this.jarFilesToDexFile = function jarFilesToDexFile(jarFiles, dexFile) {
        var Main = com.android.dx.command.dexer.Main
        var arguments = new Main.Arguments()
        arguments.fileNames = jarFiles
        arguments.outName = dexFile
        //arguments.jarOutput = true;//设置为true时生成的是优化的jar包
        Main.run(arguments)
    }

    /*
        功能与 runtime.loadDex 类似
        不会把dex加载到全局,无效重启autojs,就能重新加载,方便测试用
        加载冲突的类不会卡死挂掉
        var mDexFileLoad=new DexFileLoad(dexFilePath)//绝对路径
        var Test=mDexFileLoad.importClass("abc.Test")
    */
    this.DexFileLoad = new function() {
        var topThis = this
        var mclassLoader = context.getClass().getClassLoader()
        //files.removeDir(new java.io.File(context.getFilesDir(),"mCache"))
        var cacheDirPath = new java.io.File(context.getFilesDir(), "mCache")

        function DexFileLoad(dexFilePath) {
            if (!this instanceof arguments.callee) return new arguments.callee(dexFilePath)
            dexFilePath = new java.io.File(dexFilePath)
            var fileWorkPath = new java.io.File(cacheDirPath, dexFilePath.name)
            files.copy(dexFilePath, fileWorkPath) //必须复制到数据目录,不然卡死挂掉
            this.mDexClassLoader = new Packages.dalvik.system.DexClassLoader(fileWorkPath, null, null, mclassLoader)
        }
        DexFileLoad.prototype.importClass = function(className) {
            var mClass = this.mDexClassLoader.loadClass(className)
            return new Packages.org.mozilla.javascript.NativeJavaClass(topThis, mClass)
        }
        return DexFileLoad
    }

    /*
        编译js文件为class文件
        不支持let xx=1;语法
        文件名应尽量和变量名规则一样
        jsFiles 绝对路径 如jsc(["/sdcard/a.js"])
    */
    this.jsc = function jsc(jsFiles) {
        org.mozilla.javascript.tools.jsc.Main.main(jsFiles)
    }

    /*
        压缩多个文件,生成的zip文件没有父路径
        jsFiles 要压缩的绝对路径数组
        mZipFile 输出的绝对路径
    */
    this.zipFiles = function zipFiles(mfiles, mZipFile) {
        mZipFile = new java.io.File(mZipFile)
        mZipFile.delete()
        var mArrayList = new java.util.ArrayList
        mfiles.forEach(file => {
            mArrayList.add(new java.io.File(file))
        })
        new net.lingala.zip4j.core.ZipFile(mZipFile).addFiles(mArrayList, new net.lingala.zip4j.model.ZipParameters())
    }

}






//方便修改路径
String.prototype.rename = function(extensionName) {
    return this.replace(/\b\w+$/, extensionName)
}






//创建一个普通脚本文件
var path="/sdcard/脚本/测试/dex2js/abc.js"
js2dexTool.jsc([path.rename("js")])//编译
js2dexTool.zipFiles([path.rename("class")],path.rename("jar"))//压缩
js2dexTool.jarFilesToDexFile([path.rename("jar")],path.rename("dex"))//转换

